package com.hengpeng.itfin.service.assign.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.util.DateTimeUtil;
import com.hengpeng.common.util.MoneyUtil;
import com.hengpeng.itfin.service.assign.AssignService;
import com.hengpeng.itfin.service.impl.BaseServiceImpl;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.RespCodeConstants.CommonCode;
import com.hengpeng.itfinbase.message.partner.CreditAssignRequest;
import com.hengpeng.itfinbase.message.partner.CreditAssignResponse;
import com.hengpeng.itfinbase.persist.AccountLog.TradeMode;
import com.hengpeng.itfinbase.persist.AccountLog.TransType;
import com.hengpeng.itfinbase.persist.BorrowInfo;
import com.hengpeng.itfinbase.persist.CreditAssign;
import com.hengpeng.itfinbase.persist.CreditAssign.AssignStatus;
import com.hengpeng.itfinbase.persist.InvestInfo;
import com.hengpeng.itfinbase.persist.UserInfo;

@Service
@Lazy
@Transactional
public class AssignServiceImpl extends BaseServiceImpl implements AssignService
{
	@Override
	public CreditAssignResponse createAssign(CreditAssignRequest reqMsg)
	{
		CreditAssignResponse response = new CreditAssignResponse();
		InvestInfo invest = serviceFactory.getPersistService().get(InvestInfo.class, reqMsg.getInvestInfoId());
		BorrowInfo borrowInfo = serviceFactory.getPersistService().get(BorrowInfo.class, invest.getBorrowInfoId());
		CreditAssign creditAssign = new CreditAssign();
		creditAssign.setBorrowInfoId(borrowInfo.getId());
		creditAssign.setBorrowName(borrowInfo.getBorrowName());
		creditAssign.setBorrowRate(borrowInfo.getBorrowRate());
		creditAssign.setBorrowMoney(borrowInfo.getBorrowMoney());
		creditAssign.setRepaymentType(borrowInfo.getRepaymentType());
		creditAssign.setInvestInfoId(invest.getId());
		creditAssign.setInvestMoney(invest.getInvestMoney());
		creditAssign.setSellUserId(invest.getNowOwnUserId());
		creditAssign.setSellTrustAccountId(invest.getNowOwnUserTrustAccountId());
		creditAssign.setStatus(CreditAssign.AssignStatus.PUBLISHED);
		creditAssign.setAssignDuration(reqMsg.getAssign_duration());// 债权认购期限
		creditAssign.setCreateTime(new Date());
		creditAssign.setUpdateTime(new Date());
		creditAssign = serviceFactory.getPersistService().save(creditAssign);
		if (creditAssign.getId() == null)
		{
			response.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
			response.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
		}
		return response;
	}

	@Override
	public void packCreditAssing(CreditAssignRequest reqMsg)
	{
		CreditAssign creditAssign = serviceFactory.getPersistService().get(CreditAssign.class,
				Long.parseLong(reqMsg.getOrdId()));
		creditAssign.setStatus(AssignStatus.ASSIGNING);
		creditAssign.setSellMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getCreditAmt())));
		creditAssign.setLeftPlanNum(reqMsg.getLeftPlanNum());
		creditAssign.setLeftMoney(reqMsg.getLeftMoney());
		creditAssign.setBuyUserId(Long.parseLong(reqMsg.getBuyUserId()));
		creditAssign.setBuyTrustAccountId(reqMsg.getBuyCustId());
		creditAssign.setBuyMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getCreditDealAmt())));
		creditAssign.setRepaymentedMoney(reqMsg.getRepaymentedMoney());
		creditAssign.setFeeMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getFee())));
		serviceFactory.getPersistService().update(creditAssign);
	}

	/**
	 * <pre>
	 * 失败：
	 * 1,更新债权转让信息状态为：发布中
	 * 成功:
	 * 1,更新债权转让信息状态为成功
	 * 2,更新投标信息的当前债权人
	 * 3,添加出让人的资金流水
	 * 4,添加承接人的资金流水
	 * </pre>
	 */
	@Override
	public ServiceResult<String> dealAssignResult(CreditAssignResponse response)
	{
		ServiceResult<String> result = new ServiceResult<String>();
		if (response == null || !CommonCode.TRANS_SUC.equals(response.getRespCode()))
		{
			result.setIsSuccess(false);
			// 失败
			CreditAssign creditAssign = serviceFactory.getDaoFactory().getCommonDao()
					.lockObject(CreditAssign.class, Long.parseLong(response.getOrdId()));
			if (creditAssign != null && creditAssign.getStatus().equals(CreditAssign.AssignStatus.ASSIGNING))
			{
				creditAssign.setStatus(CreditAssign.AssignStatus.PUBLISHED);// 回退状态为：发布中
				creditAssign.setUpdateTime(new Date());
				serviceFactory.getDaoFactory().getCommonDao().updateEntity(creditAssign);
			}
			else
			{
				result.setMessage(RespCodeConstants.CommonCode.TRANS_FAIL);
				result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
			}
			return result;
		}
		else if (CommonCode.TRANS_SUC.equals(response.getRespCode()))
		{
			// 成功
			CreditAssign creditAssign = serviceFactory.getDaoFactory().getCommonDao()
					.lockObject(CreditAssign.class, Long.parseLong(response.getOrdId()));
			if (creditAssign != null && creditAssign.getStatus().equals(AssignStatus.ASSIGNING))
			{
				creditAssign.setStatus(CreditAssign.AssignStatus.ASSIGNSUCCESS);
				creditAssign.setUpdateTime(new Date());
				creditAssign.setAssignSuccessTime(new Date());
				serviceFactory.getDaoFactory().getCommonDao().updateEntity(creditAssign);

				UserInfo buyUserInfo = serviceFactory.getPersistService().get(UserInfo.class,
						creditAssign.getBuyUserId());
				InvestInfo investInfo = serviceFactory.getDaoFactory().getCommonDao()
						.getEntity(InvestInfo.class, creditAssign.getInvestInfoId());
				investInfo.setNowOwnUserId(creditAssign.getBuyUserId());
				investInfo.setNowOwnUserName(buyUserInfo.getRealName());
				investInfo.setNowOwnUserTrustAccountId(creditAssign.getBuyTrustAccountId());
				investInfo.setUpdateTime(new Date());
				serviceFactory.getDaoFactory().getCommonDao().updateEntity(investInfo);
				Long fee = MoneyUtil.convertLongYuanToFen(Double.parseDouble(response.getFee()));
				serviceFactory.getAccountService().changeAccountMoney(creditAssign.getSellUserId(),
						creditAssign.getBuyMoney(), TransType.CREDITASSIGN, TradeMode.ADD,
						creditAssign.getId().toString(), "债权转让收入");// 添加出让人资金流水

				serviceFactory.getAccountService().changeAccountMoney(creditAssign.getSellUserId(), fee,
						TransType.CREDITASSIGN_FEE, TradeMode.SUBTRACT, creditAssign.getId().toString(), "债权转让手续费扣款");// 债权转让手续费扣款

				serviceFactory.getAccountService().changeAccountMoney(creditAssign.getBuyUserId(),
						creditAssign.getBuyMoney(), TransType.CREDITASSIGN, TradeMode.SUBTRACT,
						creditAssign.getId().toString(), "投资人债权承接付款");// 添加承接人的资金流水

				result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
				result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
				result.setIsSuccess(true);
			}
			else
			{
				result.setIsSuccess(true);
				result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
				result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
			}
		}
		return result;
	}

	@Override
	public List<CreditAssign> getCreditAssigns(AssignStatus[] status)
	{
		DynamicQuery query = new DynamicQuery(CreditAssign.class);
		if (status != null && status.length > 0)
		{
			query.inArray("status", status);
		}
		return serviceFactory.getPersistService().findByDynamicQuery(CreditAssign.class, query);
	}

	@Override
	public void endAssign(List<CreditAssign> creditAssigns)
	{
		try
		{
			if (creditAssigns != null && creditAssigns.size() > 0)
			{
				List<Future<Long>> rtList = new ArrayList<Future<Long>>();
				ExecutorService execute = Executors.newFixedThreadPool(creditAssigns.size());
				for (final CreditAssign iv : creditAssigns)
				{
					Future<Long> submit = execute.submit(new Callable<Long>()
					{
						public Long call()
						{
							try
							{
								serviceFactory.getAssignService().doEndAssign(iv);
							}
							catch (Throwable e)
							{
								logger.error("债权转让过期截止检查线程异常", e);
							}
							return 0L;
						}
					});
					rtList.add(submit);
				}
				execute.shutdown();
				for (Future<Long> future : rtList)
				{
					future.get();
				}
			}
		}
		catch (Throwable e)
		{
			logger.error("债权转让过期截止检查线程异常", e);
		}
	}

	@Override
	public void doEndAssign(CreditAssign creditAssign)
	{
		Date time = DateTimeUtil.addDate(creditAssign.getCreateTime(), creditAssign.getAssignDuration());
		if (time.getTime() < System.currentTimeMillis())
		{
			creditAssign.setStatus(AssignStatus.ASSIGNFAIL);
			creditAssign.setUpdateTime(new Date());
			serviceFactory.getPersistService().update(creditAssign);
		}
	}
}
